The canonical values behind every OnWeight screen — colour, type, spacing, radii, shadow and motion. These are the Balanced theme tokens, the shipping direction used across All Screens and the Prototype. Copy them straight into a platform Theme. (Two alternate themes — Classic, Full-Editorial — exist in fc-shared.jsx; Balanced is the one to build.)
A warm-paper neutral ramp, near-black ink, one red accent, and a green/amber/red tone set for pace verdicts. We target WCAG 2.2 AA as a minimum and AAA wherever possible — every core text pairing below clears AA, and most clear AAA (ratios shown).
Meaning is never carried by colour alone — every pace verdict pairs its tone with a word (“Making weight”, “Off the pace”). Red is reserved for genuine risk; the soft tints (11–15% alpha) are for badge/callout fills, never text.
One red action only: the Hero button — logging today's weight, the daily habit the app is built around. Every other primary action uses ink (PrimaryButton). Red never competes with itself on a screen. See Component Specs.
The menstrual-cycle visuals carry a four-phase palette, and two onboarding/instrument accents sit outside the core tokens. Logged here so they are part of the system, not loose values in the code.
Phase colours appear as bands at ~12% opacity and as full-strength ring/markers — never as body text. Ovulation and Follicular fail AA as text on light, so they only ever sit behind a text label or position (which also serves colour-blind athletes). Pace-gold #C9A23A and inverted red #F4A299 are legible only on ink/dark and are used there exclusively.
Fills and overlays use a small, consistent set of alphas so charts and tints feel like one hand drew them.
| Alpha | Where |
|---|---|
| 0.10–0.14 | Target-zone & tone-band fills, soft callout tints, cycle phase bands (0.12) |
| 0.26–0.40 | Raw weigh-in dots on the trend (recessive) |
| ~0.40 | Scrubber / today divider lines |
| 0.50–0.70 | Gridlines & hairlines inside charts |
| 0.14 → 0.03 → 0 | Trend-area gradient fill (top → fade) |
| 0.045–0.05 | Poster hatch / grid motif overlays |
Computed ratios for every text/icon colour against the three real surfaces. AA needs ≥ 4.5:1 (normal text), AAA ≥ 7:1; non-text graphics need ≥ 3:1. This is why status text uses --t-amber #6F5210 while chart strokes use --mustard-deep #A87B22 (a graphic).
| Foreground | on Paper #fff | on Page #f9f7f2 | on Ink #15140f |
|---|---|---|---|
| Ink #15140F | 18.4 · AAA | 17.2 · AAA | — |
| Ink-2 #3A3833 | 11.7 · AAA | 10.9 · AAA | — |
| Ink-3 #524D44 | 8.4 · AAA | 7.8 · AAA | — |
| Accent #A32A18 | 7.2 · AAA | 6.8 · AA | 2.6 · graphic-fail |
| Green #2F5A24 | 8.1 · AAA | 7.5 · AAA | — |
| Amber-text #6F5210 | 7.3 · AAA | 6.8 · AA | — |
| Mustard-deep #A87B22 | 3.8 · graphic only | 3.6 · graphic only | 4.9 · AA |
| Rule-2 #8A7F68 | 3.95 · graphic only | 3.7 · graphic only | 4.7 · AA |
| Menstrual #B0432F | 5.7 · AA | 5.3 · AA | 3.2 · graphic |
| Luteal #7A6AA0 | 4.8 · AA | 4.5 · AA* | 3.9 · graphic |
| Follicular #6B8F5A | 3.7 · graphic only | 3.4 · graphic only | 5.0 · AA |
| Ovulation #C79A3A | 2.6 · fail | 2.4 · fail | 7.1 · AAA |
*Luteal on the off-white page is 4.46 — a hair under AA for small text; it is only used as a band/marker, never as body text. “Graphic” = clears the 3:1 bar for non-text UI (icons, strokes, borders) but not the 4.5:1 text bar. Ratios recomputed June 2026; see Accessibility Pass for the policy.
Three families: Oswald (eyebrows & section labels), IBM Plex Sans (UI text & the big numerals, with tnum tabular figures), IBM Plex Mono (data labels & meta). IBM Plex Serif appears only in the coach's-read quote. Map each role to a scalable text style — never a literal px — with an 11px floor (see Accessibility Pass).
Numerals use tabular figures (font-feature-settings:"tnum") everywhere they change, so values don't reflow. Body uses text-wrap:pretty; titles text-wrap:balance.
A 4px base scale. Card padding sits at 18–22, screen gutters at 20, stacked-card gaps at 18–20. Touch targets never below 44pt.
| Target | Min size | Notes |
|---|---|---|
| Primary CTA | 54–56px | Full-width buttons |
| List row | 50px+ | Tap-through rows |
| Icon button | 44×44pt | Back/close visual 38px → expand hit area to 44 |
| Motion token | Value | Use |
|---|---|---|
| Transition · base | 260ms · cubic-bezier(0.22,0.61,0.36,1) | Screen/state changes, slide-in |
| Transition · fast | 150ms · ease | Hovers, small affordances |
| Reduced motion | prefers-reduced-motion | Drop entrance animations to instant — always honoured |
No infinite decorative loops on content. Entrance animations animate from hidden to the visible base state, gated on reduced-motion so print/PDF/AT show content.
Verbatim from fc-shared.jsx → THEMES.balanced.vars. Drop into a platform theme as-is.
| --paper / --paper-2 | #ffffff / #f1ede6 |
| --ink / --ink-2 / --ink-3 | #15140f / #3a3833 / #524d44 |
| --rule / --rule-2 | #e6ded2 / #8a7f68 |
| --accent / --accent-soft | #a32a18 / rgba(163,42,24,0.10) |
| --t-green / -soft | #2f5a24 / rgba(58,107,46,0.13) |
| --t-amber / -soft | #6f5210 / rgba(168,123,34,0.15) |
| --t-red / -soft | #a32a18 / rgba(163,42,24,0.11) |
| --radius / --radius-ctl | 20px / 14px |
| --card-shadow | 0 1px 3px rgba(20,18,12,.04), 0 8px 22px rgba(20,18,12,.05) |
| --display / --num / --title | Oswald / IBM Plex Sans / IBM Plex Sans |
| --title-spacing / --eyebrow-spacing | -0.03em / 0.16em |
Companion to the component specs (next), the Accessibility Pass (contrast ratios cited above), and fc-shared.jsx (source of truth).